#include <curveeditor.h>
#include <QPainter>
#include <QMouseEvent>
#include <QPen>
#include <QBrush>
#include <QLinearGradient>
#include <QStyleOption>
#include <algorithm>

CurveEditor::CurveEditor(QWidget *parent)
    : QWidget(parent)
{
    setMinimumSize(400, 260);
    m_contentRect = rect().adjusted(60, 20, -20, -60);
    
    // 设置背景色
    setAutoFillBackground(true);
    QPalette palette;
    palette.setColor(QPalette::Window, QColor(225, 225, 225));
    setPalette(palette);
}

void CurveEditor::setSize(int width, int height) 
{
    setFixedSize(width, height);
    m_contentRect = rect().adjusted(60, 20, -20, -60);
    update();
}

void CurveEditor::setPoints(const QVector<CurvePoint> &points)
{
    m_points = points;
    m_originalPoints = points;
    validateCurve();
    update();
}

QVector<CurvePoint> CurveEditor::getCurrentPoints() const
{
    return m_points;
}

void CurveEditor::setGridWidth(int width) 
{
    gridWidth = width;
    update();
}

void CurveEditor::setGridHeight(int height) 
{
    gridHeight = height;
    update();
}

void CurveEditor::setXTickTag(std::string tag) 
{
    xTickTag = tag;
    update();
}

void CurveEditor::setYTickTag(std::string tag)
{
    yTickTag = tag;
    update();
}

void CurveEditor::setYTickStep(int step) 
{
    yTickStep = step;
    update();
}

void CurveEditor::setXTickStep(int step) 
{
    xTickStep = step;
    update();
}

void CurveEditor::setYTickRange(int min, int max) 
{
    yTickMin = min;
    yTickMax = max;
    update();
}

void CurveEditor::setXTickRange(int min, int max) 
{
    xTickMin = min;
    xTickMax = max;
    update();
}

void CurveEditor::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setRenderHint(QPainter::SmoothPixmapTransform, true);

    // 绘制背景和样式
    QStyleOption opt;
    opt.initFrom(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);

    // 绘制网格
    painter.save();
    QPen gridPen(QColor(60, 60, 60), 0.5);
    gridPen.setStyle(Qt::DotLine);
    painter.setPen(gridPen);

    // 横向网格线
    for (int i = 0; i <= gridHeight; ++i)
    {
        qreal y = m_contentRect.top() + (m_contentRect.height() * (qreal)i / gridHeight);
        painter.drawLine(m_contentRect.left(), y, m_contentRect.right(), y);
    }

    // 纵向网格线
    for (int i = 0; i <= gridWidth; ++i)
    {
        qreal x = m_contentRect.left() + (m_contentRect.width() * (qreal)i / gridWidth);
        painter.drawLine(x, m_contentRect.top(), x, m_contentRect.bottom());
    }
    painter.restore();

    // 绘制坐标轴
    painter.save();
    QPen axisPen(QColor(80, 80, 80), 2.0);
    painter.setPen(axisPen);
    painter.drawLine(m_contentRect.left(), m_contentRect.bottom(),
                     m_contentRect.right(), m_contentRect.bottom()); // X轴
    painter.drawLine(m_contentRect.left(), m_contentRect.top(),
                     m_contentRect.left(), m_contentRect.bottom()); // Y轴
    painter.restore();

    // 绘制坐标轴刻度
    painter.save();
    QFont tickFont = painter.font();
    tickFont.setPointSize(8);
    painter.setFont(tickFont);
    
    // X轴刻度
    painter.setPen(QPen(QColor(60, 60, 60), 1.5));
    for (int i = xTickMin; i <= xTickMax; i += xTickStep)
    {
        qreal xPos = m_contentRect.left() + (m_contentRect.width() * i / ((qreal)gridWidth * 10));
        QString label = QString::number(i);

        // 绘制刻度线
        painter.drawLine(xPos, m_contentRect.bottom(),
                         xPos, m_contentRect.bottom() + 6);

        // 绘制刻度文本
        QRect textRect(xPos - 20, m_contentRect.bottom() + 8, 40, 15);
        painter.drawText(textRect, Qt::AlignCenter, label);
    }

    // Y轴刻度
    for (int i = yTickMin; i <= yTickMax; i += yTickStep)
    {
        qreal yPos = m_contentRect.bottom() - (m_contentRect.height() * i / ((qreal)gridHeight * 10));
        QString label = QString::number(i);

        // 绘制刻度线
        painter.drawLine(m_contentRect.left(), yPos,
                         m_contentRect.left() - 6, yPos);

        // 绘制刻度文本
        QRect textRect(m_contentRect.left() - 45, yPos - 8, 40, 15);
        painter.drawText(textRect, Qt::AlignRight | Qt::AlignVCenter, label);
    }

    // 添加坐标轴标签
    QFont labelFont = painter.font();
    labelFont.setPointSize(10);
    labelFont.setBold(true);
    painter.setFont(labelFont);
    
    painter.setPen(QColor(40, 40, 40));
    QRect xLabelRect(m_contentRect.right() - 80, m_contentRect.bottom() + 25, 100, 20);
    painter.drawText(xLabelRect, Qt::AlignCenter, xTickTag.c_str());

    painter.save();
    painter.rotate(-90);
    QRect yLabelRect(-m_contentRect.bottom() - 15, m_contentRect.left() - 55, 120, 20);
    painter.drawText(yLabelRect, Qt::AlignCenter, yTickTag.c_str());
    painter.restore();

    painter.restore();

    // 绘制曲线
    painter.save();
    QPen curvePen(QColor(65, 105, 225), 3.0);
    curvePen.setCapStyle(Qt::RoundCap);
    curvePen.setJoinStyle(Qt::RoundJoin);
    painter.setPen(curvePen);

    for (int i = 1; i < m_points.size(); ++i)
    {
        QPointF p1 = mapToContent(m_points[i - 1].x, m_points[i - 1].y);
        QPointF p2 = mapToContent(m_points[i].x, m_points[i].y);
        painter.drawLine(p1, p2);
    }

    // 绘制节点
    for (int i = 0; i < m_points.size(); ++i)
    {
        QPointF pos = mapToContent(m_points[i].x, m_points[i].y);
        painter.save();
        
        // 创建节点渐变效果
        QRadialGradient gradient(pos, POINT_RADIUS * 1.5);
        if (isDragging() && m_dragIndex == i)
        {
            gradient.setColorAt(0, QColor(255, 100, 100));
            gradient.setColorAt(1, QColor(220, 20, 60));
        }
        else
        {
            gradient.setColorAt(0, QColor(70, 130, 255));
            gradient.setColorAt(1, QColor(30, 144, 255));
        }
        
        painter.setBrush(QBrush(gradient));
        painter.setPen(QPen(QColor(255, 255, 255), 1.5));
        painter.drawEllipse(pos, POINT_RADIUS, POINT_RADIUS);
        
        // 添加高光效果
        if (POINT_RADIUS > 3) {
            painter.setBrush(QBrush(QColor(255, 255, 255, 120)));
            painter.setPen(Qt::NoPen);
            painter.drawEllipse(pos.x() - POINT_RADIUS * 0.3, 
                              pos.y() - POINT_RADIUS * 0.3, 
                              POINT_RADIUS * 0.6, POINT_RADIUS * 0.6);
        }
        
        painter.restore();
    }
    painter.restore();
}

QPointF CurveEditor::mapToContent(qreal xPercent, qreal yPercent)
{
    qreal x = m_contentRect.left() + (m_contentRect.width() * xPercent / 100.0);
    qreal y = m_contentRect.bottom() - (m_contentRect.height() * yPercent / 100.0);
    return QPointF(x, y);
}

int CurveEditor::findPointAt(const QPointF &pos)
{
    for (int i = 0; i < m_points.size(); ++i)
    {
        QPointF pt = mapToContent(m_points[i].x, m_points[i].y);
        if (QLineF(pt, pos).length() < POINT_RADIUS * 1.5) // 稍微增加点击区域
        {
            return i;
        }
    }
    return -1;
}

void CurveEditor::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        m_dragIndex = findPointAt(event->pos());
        if (m_dragIndex >= 0)
        {
            m_dragStartPos = event->pos();
            setCursor(Qt::ClosedHandCursor);
        }
    }
}

void CurveEditor::mouseMoveEvent(QMouseEvent *event)
{
    if (isDragging())
    {
        QPointF delta = event->pos() - m_dragStartPos;

        // 计算新的坐标
        QPointF newPos = mapToContent(m_points[m_dragIndex].x, m_points[m_dragIndex].y) + delta;
        m_points[m_dragIndex].x = qBound(0.0, (newPos.x() - m_contentRect.left()) * 100.0 / m_contentRect.width(), 100.0);
        m_points[m_dragIndex].y = qBound(0.0, (m_contentRect.bottom() - newPos.y()) * 100.0 / m_contentRect.height(), 100.0);

        adjustPointPosition(m_dragIndex);
        validateCurve();
        update();
        m_dragStartPos = event->pos();
        emit curveChanged(m_points);
    }
}

void CurveEditor::mouseReleaseEvent(QMouseEvent *event)
{
    if (isDragging())
    {
        unsetCursor();
        m_dragIndex = -1;
    }
    emit curveReleased();
}

void CurveEditor::adjustPointPosition(int index)
{
    const qreal minGap = 0.1; // 最小间距阈值

    // 处理与前一个点的关系
    if (index > 0)
    {
        // 确保当前点X坐标大于前一个点，并保持最小间距
        if (m_points[index].x <= m_points[index - 1].x + minGap)
        {
            m_points[index].x = m_points[index - 1].x + minGap;
        }
        
        // 确保当前点Y坐标大于前一个点，并保持最小间距
        if (m_points[index].y <= m_points[index - 1].y + minGap)
        {
            m_points[index].y = m_points[index - 1].y + minGap;
        }
    }

    // 处理与后一个点的关系
    if (index < m_points.size() - 1)
    {
        // 确保当前点X坐标小于后一个点，并保持最小间距
        if (m_points[index].x >= m_points[index + 1].x - minGap)
        {
            m_points[index].x = m_points[index + 1].x - minGap;
        }
        
        // 确保当前点Y坐标小于后一个点，并保持最小间距
        if (m_points[index].y >= m_points[index + 1].y - minGap)
        {
            m_points[index].y = m_points[index + 1].y - minGap;
        }
    }
}

void CurveEditor::validateCurve()
{
    // 按X坐标排序
    std::sort(m_points.begin(), m_points.end(), 
        [](const CurvePoint& a, const CurvePoint& b) { return a.x < b.x; });
    
    // 应用间距规则
    for (int i = 0; i < m_points.size(); ++i) {
        adjustPointPosition(i);
    }
}